home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / dosfs / dmsdosfs.000 / dmsdosfs / dmsdosfs-0.6.9b / dmsdos_std.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  25KB  |  907 lines

  1. /*
  2. linux/fs/dmsdos/dmsdos_std.c
  3.  
  4. DMSDOS filesystem: standard routines.
  5.  
  6. This file adapts the standard Linux filesystem interface to the dmsdos
  7. routines and decides whether to call msdos/vfat or dmsdos for the desired
  8. operation.
  9.  
  10. ******************************************************************************
  11. DMSDOS (Doublespace/Drivespace compressed MSDOS filesystem) for Linux
  12. written 1995,1996 by Frank Gockel
  13.  
  14.     (C) Copyright 1995,1996 by Frank Gockel
  15.  
  16. Some code of the dmsdos filesystem has been copied from the msdos filesystem
  17. so there are the following additional copyrights:
  18.  
  19.     (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
  20.     (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
  21.     (C) Copyright 1992-1995 by Linus Torvalds
  22.  
  23. The DMSDOS filesystem was inspired by the THS filesystem (a simple doublespace
  24. DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
  25.  
  26. The DMSDOS filesystem is distributed under the Gnu General Public Licence.
  27. See file COPYING for details.
  28. ******************************************************************************
  29.  
  30. */
  31.  
  32. #include <linux/sched.h>
  33. #include <linux/ctype.h>
  34. #include <linux/major.h>
  35. #include <linux/blkdev.h>
  36. #include <linux/fs.h>
  37. #include <linux/stat.h>
  38. #include <linux/locks.h>
  39. #include <asm/segment.h>
  40. #include <linux/mm.h>
  41. #include <linux/malloc.h>
  42. #include <linux/string.h>
  43. #include <linux/msdos_fs.h>
  44. #include <linux/dmsdos_fs.h>
  45. #include <linux/errno.h>
  46. #include <linux/kernel.h>
  47. #include <linux/shm.h>
  48. #include <linux/mman.h>
  49. #include <asm/system.h>
  50.  
  51. #ifdef __FOR_KERNEL_1_3_8x
  52. #include <linux/module.h>
  53. #else
  54. /*define empty MOD macros for older kernels... in order to ignore module...*/
  55. #define MOD_INC_USE_COUNT
  56. #define MOD_DEC_USE_COUNT
  57. #endif
  58.  
  59. #ifdef MODULE
  60. #ifndef __FOR_KERNEL_1_3_8x
  61. #error DMSDOS: module support requires newer kernel > 1.3.80, sorry.
  62. #endif
  63. #endif
  64.  
  65. /* default compression mode,
  66.    you should use READ_ONLY or GUESS, further possibilities see dmsdos_fs.h */
  67. #define DEFAULT_COMP GUESS
  68.  
  69. /* default compression level -1 */
  70. /* 0=least efficient but fastest compression
  71.    11=most efficient but slowest compression */
  72. #define DEFAULT_CF   11
  73.  
  74. /* vfat support (only for kernel >= 1.3.81) */
  75. #ifdef CONFIG_DMSDOS_UPON_VFAT
  76. #define SUPPORT_VFAT
  77. #endif
  78.  
  79. /* writable mmap support (requires kernel >=1.3.81) */
  80. /* defining USE_READPAGE causes the driver to use the new mmap code.
  81.    WARNING: This is very _experimental_ and may crash your system horribly
  82.    and mess up your compressed _and_ uncompressed dos filesystems.
  83.    This is currently not tested enough, so be extremely careful. */
  84. #ifdef __FOR_KERNEL_1_3_8x
  85. #define USE_READPAGE
  86. #endif
  87.  
  88. /* initialization routines.... */
  89.  
  90. static struct file_system_type dmsdos_fs_type =
  91. {dmsdos_read_super,"dmsdos",1,NULL};
  92.  
  93. #ifdef __FOR_KERNEL_1_3_8x
  94. #ifdef USE_READPAGE
  95. /* must be known because this should be exported */
  96. int dmsdos_readpage(struct inode *inode, struct page *page);
  97. #endif
  98. static struct symbol_table dmsdos_syms = {
  99. #include<linux/symtab_begin.h>
  100.      X(dmsdos_readdir),
  101.      X(dmsdos_file_read),
  102.      X(dmsdos_file_write),
  103.      X(dmsdos_create),
  104.      X(dmsdos_lookup),
  105.      X(dmsdos_read_super),
  106.      X(dmsdos_rename),
  107.      X(dmsdos_unlink),
  108.      X(dmsdos_rmdir),
  109.      X(dmsdos_mkdir),
  110.      X(dmsdos_unlink_umsdos),
  111.      X(dmsdos_truncate),
  112.      X(dmsdos_mmap),
  113.      X(dmsdos_put_inode),
  114.      X(dmsdos_put_super),
  115.      X(dmsdos_statfs),
  116.      X(dmsdos_read_inode),
  117.      X(dmsdos_write_inode),
  118.      X(dmsdos_notify_change),
  119.      X(dmsdos_ioctl_dir),
  120.      X(dbltest),
  121.      X(dostest),
  122. #ifdef USE_READPAGE
  123.      X(dmsdos_readpage),
  124. #endif
  125. #include<linux/symtab_end.h>
  126. };
  127. #endif
  128.  
  129. int init_dmsdos_fs(void)
  130. { int status;
  131.  
  132.   status=register_filesystem(&dmsdos_fs_type);
  133. #ifdef __FOR_KERNEL_1_3_8x
  134.   if(status==0)status=register_symtab(&dmsdos_syms);
  135. #endif
  136.   return status;
  137. }
  138.  
  139. #ifdef MODULE
  140.  
  141. int init_module(void)
  142. {  return init_dmsdos_fs();
  143. }
  144.  
  145. int cleanup_module(void)
  146. {  return unregister_filesystem(&dmsdos_fs_type);
  147. }
  148.  
  149. #endif /*MODULE*/
  150.  
  151. #ifdef SUPPORT_VFAT
  152.  
  153. extern Dblsb dblsb[];
  154. extern int dbl_sb_dev[];
  155.  
  156. int isvfat(struct super_block*sb)
  157. { int i;
  158.  
  159.   for(i=0;i<MAXDBLFILES;++i)
  160.   { if(dbl_sb_dev[i]==sb->s_dev)
  161.       return (dblsb[i].s_support_lfn&4);
  162.   }
  163.   return 0;
  164. }
  165.  
  166. #endif /* SUPPORT_VFAT */
  167.  
  168.  
  169. #ifdef USE_READPAGE
  170.  
  171. /* Grmpf.... partially untested code. Don't know an application that does
  172.    writable mmaps, but it would be needed for testing this piece of code */
  173.    
  174. /* idea: kernel does buffer reads with bmap calculated buffers - impossible
  175.          for dmsdos. (see kernel mmap code).
  176.          kernel emulates writable mmap by calling file_write when no buffers
  177.          are present - should work for dmsdos.
  178.          so I do file_read-emulated readable mmaps here though the
  179.          generic_mmap function is used.
  180. */
  181.    
  182. int read_the_page(unsigned long address, unsigned long pos,
  183.                    struct inode*inode, int fs_type)
  184. {
  185.     unsigned int clear;
  186.     long gap;    /* distance from eof to pos */
  187.     
  188.     /*printk("DMSDOS: read_the_page\n");*/
  189.  
  190.     address &= PAGE_MASK;
  191.  
  192.     clear = 0;
  193.     gap = inode->i_size - pos;
  194.     if (gap <= 0){
  195.         /* mmaping beyond end of file */
  196.         clear = PAGE_SIZE;
  197.     }else{
  198.         int cur_read;
  199.         int need_read;
  200.         struct file filp;
  201.         if (gap < PAGE_SIZE){
  202.             clear = PAGE_SIZE - gap;
  203.         }
  204.         filp.f_reada = 0;
  205.         filp.f_pos = pos;
  206.         need_read = PAGE_SIZE - clear;
  207.         {
  208.             unsigned long cur_fs = get_fs();
  209.             set_fs (KERNEL_DS);
  210.             cur_read = fs_type ?
  211.                     fat_file_read (inode,&filp,(char*)address
  212.                 ,need_read) :
  213.                     dmsdos_file_read (inode,&filp,(char*)address
  214.                 ,need_read);
  215.             set_fs (cur_fs);
  216.         }
  217.         if (cur_read != need_read){
  218.             printk ("DMSDOS: Error while reading an mmap file %d <> %d\n"
  219.                 ,cur_read,need_read);
  220.             return -1;
  221.         }
  222.     }
  223.     if (clear > 0){
  224.         memset ((char*)address+PAGE_SIZE-clear,0,clear);
  225.     }
  226.     return 0;
  227. }
  228.  
  229. int dmsdos_readpage(struct inode *inode, struct page *page)
  230. {  unsigned long   address;
  231.    int             error = -1;
  232.                 
  233.    /*printk("DMSDOS: readpage %08lx\n", page_address(page));*/
  234.    
  235.    address = page_address(page);
  236.    page->count++;
  237.    set_bit(PG_locked, &page->flags);
  238.                    
  239.    /* wie waers wenn ich jetzt einfach lese */
  240.    error=read_the_page(address,page->offset,inode,0);
  241.            
  242.    if(error==0)set_bit(PG_uptodate, &page->flags);
  243.                    
  244.    clear_bit(PG_locked, &page->flags);
  245.    wake_up(&page->wait);
  246.                                                                                        
  247.    free_page(address);
  248.    return error;
  249. }
  250.  
  251. #ifdef NEED_FAT_READPAGE
  252. /* fat_readpage is missing in fat fs, so long..... */
  253. int fat_readpage(struct inode *inode, struct page *page)
  254. {  unsigned long   address;
  255.    int             error = -1;
  256.                 
  257.    /*printk("DMSDOS: fat_readpage %08lx\n", page_address(page));*/
  258.    
  259.    address = page_address(page);
  260.    page->count++;
  261.    set_bit(PG_locked, &page->flags);
  262.                    
  263.    /* wie waers wenn ich jetzt einfach lese */
  264.    error=read_the_page(address,page->offset,inode,1);
  265.            
  266.    if(error==0)set_bit(PG_uptodate, &page->flags);
  267.                    
  268.    clear_bit(PG_locked, &page->flags);
  269.    wake_up(&page->wait);
  270.                                                                                        
  271.    free_page(address);
  272.    return error;
  273. }
  274. #endif /* NEED_FAT_READPAGE */
  275.  
  276. #endif   /* USE_READPAGE */
  277.  
  278.  
  279. static int dmsdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
  280. {
  281.     return -EISDIR;
  282. }
  283.  
  284. static struct file_operations dmsdos_dir_operations = {
  285.     NULL,            /* lseek - default */
  286.     dmsdos_dir_read,    /* read */
  287.     NULL,            /* write - bad */
  288.     dmsdos_readdir,        /* readdir */
  289.     NULL,            /* select - default */
  290.     dmsdos_ioctl_dir,       /* ioctl - default */
  291.     NULL,            /* mmap */
  292.     NULL,            /* no special open code */
  293.     NULL,            /* no special release code */
  294.     file_fsync             /* fsync */
  295. };
  296.  
  297. struct inode_operations dmsdos_dir_inode_operations = {
  298.     &dmsdos_dir_operations,    /* default directory file-ops */
  299.     dmsdos_create,       /* create */
  300.     dmsdos_lookup,        /* lookup */
  301.     NULL,            /* link */
  302.     dmsdos_unlink,        /* unlink */
  303.     NULL,            /* symlink */
  304.     dmsdos_mkdir,       /* mkdir */
  305.     dmsdos_rmdir,       /* rmdir */
  306.     NULL,            /* mknod */
  307.     dmsdos_rename,       /* rename */
  308.     NULL,            /* readlink */
  309.     NULL,            /* follow_link */
  310. #ifdef __FOR_KERNEL_1_3_8x
  311.         NULL,                   /* readpage */
  312.         NULL,                   /* writepage */
  313. #endif
  314.     NULL,            /* bmap */
  315.     NULL,            /* truncate */
  316.     NULL            /* permission */
  317. };
  318.  
  319. #ifdef __FOR_KERNEL_1_3
  320. int dmsdos_readdir(
  321.     struct inode *inode,
  322.     struct file *filp,
  323.     void *dirent,
  324.     filldir_t filldir)
  325. {    int res;
  326.         
  327.         /*printk("DMSDOS: readdir ino=%ld\n",inode->i_ino);*/
  328.         if(dostest(inode))
  329. #ifdef __FOR_KERNEL_1_3_8x
  330.                  res=fat_readdir(inode,filp,dirent,filldir);
  331. #else
  332.                  res=msdos_readdir(inode,filp,dirent,filldir);
  333. #endif
  334.         else res=dmsdos_readdirx(inode,filp,dirent,filldir);
  335.         /*printk("DMSDOS: readdir finished res=%d\n",res);*/
  336.         return res;
  337. }
  338. #else
  339. int dmsdos_readdir(
  340.     struct inode *inode,
  341.     struct file *filp,
  342.     struct dirent *dirent,
  343.     int count)
  344. {    int res;
  345.         
  346.         /*printk("DMSDOS: readdir ino=%ld\n",inode->i_ino);*/
  347.         if(dostest(inode)) res=msdos_readdir(inode,filp,dirent,count);
  348.         else res=dmsdos_readdirx(inode,filp,dirent,count);
  349.         /*printk("DMSDOS: readdir finished res=%d\n",res);*/
  350.         return res;
  351. }
  352. #endif
  353.  
  354. static struct file_operations dmsdos_file_operations = {
  355.     NULL,            /* lseek - default */
  356.     dmsdos_file_read,    /* read */
  357.     dmsdos_file_write,      /* write */
  358.     NULL,            /* readdir - bad */
  359.     NULL,            /* select - default */
  360.     NULL,            /* ioctl - default */
  361. #ifdef USE_READPAGE
  362.         generic_file_mmap,
  363. #else
  364.     dmsdos_mmap,        /* mmap */
  365. #endif
  366.     NULL,            /* no special open is needed */
  367.     NULL,            /* release */
  368.     file_fsync            /* fsync */
  369. };
  370.  
  371. struct inode_operations dmsdos_file_inode_operations = {
  372.     &dmsdos_file_operations,    /* default file operations */
  373.     NULL,            /* create */
  374.     NULL,            /* lookup */
  375.     NULL,            /* link */
  376.     NULL,            /* unlink */
  377.     NULL,            /* symlink */
  378.     NULL,            /* mkdir */
  379.     NULL,            /* rmdir */
  380.     NULL,            /* mknod */
  381.     NULL,            /* rename */
  382.     NULL,            /* readlink */
  383.     NULL,            /* follow_link */
  384. #ifdef __FOR_KERNEL_1_3_8x
  385. #ifdef USE_READPAGE
  386.         dmsdos_readpage,
  387. #else
  388.         NULL,                   /* readpage */
  389. #endif
  390.         NULL,                   /* writepage */
  391. #endif
  392.     NULL,           /* bmap */
  393.     dmsdos_truncate,       /* truncate */
  394.     NULL,            /* permission */
  395.     NULL            /* smap */
  396. };
  397.  
  398. static struct file_operations dmsdos_file_operations_1024 = {
  399.     NULL,            /* lseek - default */
  400.     dmsdos_file_read,    /* read */
  401.     dmsdos_file_write,      /* write */
  402.     NULL,            /* readdir - bad */
  403.     NULL,            /* select - default */
  404.     NULL,            /* ioctl - default */
  405. #ifdef USE_READPAGE
  406.         generic_file_mmap,
  407. #else
  408.     dmsdos_mmap,         /* mmap */
  409. #endif
  410.     NULL,            /* no special open is needed */
  411.     NULL,            /* release */
  412.     file_fsync             /* fsync */
  413. };
  414.  
  415. struct inode_operations dmsdos_file_inode_operations_1024 = {
  416.     &dmsdos_file_operations_1024,    /* default file operations */
  417.     NULL,            /* create */
  418.     NULL,            /* lookup */
  419.     NULL,            /* link */
  420.     NULL,            /* unlink */
  421.     NULL,            /* symlink */
  422.     NULL,            /* mkdir */
  423.     NULL,            /* rmdir */
  424.     NULL,            /* mknod */
  425.     NULL,            /* rename */
  426.     NULL,            /* readlink */
  427.     NULL,            /* follow_link */
  428. #ifdef __FOR_KERNEL_1_3_8x
  429. #ifdef USE_READPAGE
  430.         dmsdos_readpage,
  431. #else
  432.         NULL,                   /* readpage */
  433. #endif
  434.         NULL,                   /* writepage */
  435. #endif
  436.     NULL,            /* bmap */
  437.     dmsdos_truncate,       /* truncate */
  438.     NULL,            /* permission */
  439.     NULL            /* smap */
  440. };
  441.  
  442. int dmsdos_file_read(
  443.     struct inode *inode,
  444.     struct file *filp,
  445.     char *buf,
  446.     int count)
  447. {       int res;
  448.  
  449.     /*res=count;
  450.           printk("DMSDOS file_read ino=%ld pos=%u count=%d\n",inode->i_ino,
  451.                filp->f_pos,res);*/
  452.         if(dostest(inode))
  453. #ifdef __FOR_KERNEL_1_3_8x 
  454.                      res=fat_file_read(inode,filp,buf,count);
  455. #else
  456.                      res=msdos_file_read(inode,filp,buf,count);
  457. #endif
  458.         else res=dmsdos_file_readx(inode,filp,buf,count);
  459.         /*printk("DMSDOS: file_read finished res=%d\n",res);*/
  460.         return res;
  461. }
  462.  
  463. int dmsdos_file_write(
  464.     struct inode *inode,
  465.     struct file *filp,
  466. #ifdef __FOR_KERNEL_1_3
  467.         const
  468. #endif
  469.     char *buf,
  470.     int count)
  471. {       int res;
  472.  
  473.         /*res=count;
  474.           printk("DMSDOS file_write ino=%ld pos=%u count=%d\n",inode->i_ino,
  475.                filp->f_pos,res);*/
  476.         if(dostest(inode))
  477. #ifdef __FOR_KERNEL_1_3_8x
  478.                      res=fat_file_write(inode,filp,buf,count);
  479. #else 
  480.                      res=msdos_file_write(inode,filp,buf,count);
  481. #endif
  482.         else res=dmsdos_file_writex(inode,filp,buf,count);
  483.         /*printk("DMSDOS: file_write finished res=%d\n",res);*/
  484.         return res;
  485. }
  486.  
  487. int dmsdos_create(
  488.     struct inode *dir,
  489.     const char*name, int len, int mode, struct inode**result)
  490. {       int res;
  491.  
  492.         /*printk("DMSDOS create ino=%ld\n",dir->i_ino);*/
  493.         if(dostest(dir)) res=
  494. #ifdef SUPPORT_VFAT
  495.                  isvfat(dir->i_sb) ? vfat_create(dir,name,len,mode,result) :
  496. #endif
  497.                     msdos_create(dir,name,len,mode,result);
  498.         else res=dmsdos_createx(dir,name,len,mode,result);
  499.         /*printk("DMSDOS: create finished res=%d\n",res);*/
  500.         return res;
  501. }
  502.  
  503. int dmsdos_unlink(struct inode *dir, const char*name, int len)
  504. {       int res;
  505.  
  506.         /*printk("DMSDOS unlink ino=%ld\n",dir->i_ino);*/
  507.         if(dostest(dir)) res=
  508. #ifdef SUPPORT_VFAT
  509.                        isvfat(dir->i_sb) ? vfat_unlink(dir,name,len) :
  510. #endif
  511.                        msdos_unlink(dir,name,len);
  512.         else res=dmsdos_unlinkx(dir,name,len);
  513.         /*printk("DMSDOS: unlink finished res=%d\n",res);*/
  514.         return res;
  515. }
  516.  
  517. int dmsdos_mkdir(struct inode *dir, const char*name, int len, int mode)
  518. {       int res;
  519.  
  520.         /*printk("DMSDOS mkdir ino=%ld\n",dir->i_ino);*/
  521.         if(dostest(dir)) res=
  522. #ifdef SUPPORT_VFAT
  523.                        isvfat(dir->i_sb) ? vfat_mkdir(dir,name,len,mode) :
  524. #endif
  525.                        msdos_mkdir(dir,name,len,mode);
  526.         else res=dmsdos_mkdirx(dir,name,len,mode);
  527.         /*printk("DMSDOS: mkdir finished res=%d\n",res);*/
  528.         return res;
  529. }
  530.  
  531. int dmsdos_rmdir(struct inode *dir, const char*name, int len)
  532. {       int res;
  533.  
  534.         /*printk("DMSDOS rmdir ino=%ld\n",dir->i_ino);*/
  535.         if(dostest(dir)) res=
  536. #ifdef SUPPORT_VFAT
  537.                       isvfat(dir->i_sb) ? vfat_rmdir(dir,name,len) :
  538. #endif
  539.                       msdos_rmdir(dir,name,len);
  540.         else res=dmsdos_rmdirx(dir,name,len);
  541.         /*printk("DMSDOS: rmdir finished res=%d\n",res);*/
  542.         return res;
  543. }
  544.  
  545. int dmsdos_rename(struct inode *old_dir, const char*old_name, int old_len,
  546.                   struct inode *new_dir, const char*new_name, int new_len
  547. #ifdef __FOR_KERNEL_2_0_1
  548.                   ,int must_be_dir
  549. #endif
  550.                   )
  551. {    int res;       
  552.  
  553.     /*printk("DMSDOS rename ino=%ld\n",old_dir->i_ino);*/
  554.         if(dostest(old_dir)&&dostest(new_dir))
  555.              res=
  556. #ifdef SUPPORT_VFAT
  557.                  isvfat(old_dir->i_sb) ?
  558.                  vfat_rename(old_dir,old_name,old_len,
  559.                              new_dir,new_name,new_len
  560. #ifdef __FOR_KERNEL_2_0_1
  561.                              ,must_be_dir
  562. #endif
  563.                              ) :
  564. #endif
  565.                  msdos_rename(old_dir,old_name,old_len,
  566.                               new_dir,new_name,new_len
  567. #ifdef __FOR_KERNEL_2_0_1
  568.                               ,must_be_dir
  569. #endif
  570.                               );
  571.         else res=dmsdos_renamex(old_dir,old_name,old_len,
  572.                                 new_dir,new_name,new_len
  573. #ifdef __FOR_KERNEL_2_0_1
  574.                                 ,must_be_dir
  575. #endif
  576.                                 );
  577.         /*printk("DMSDOS: rename finished res=%d\n",res);*/
  578.         return res;
  579. }
  580.  
  581. void dmsdos_truncate(struct inode *inode)
  582. {    /*printk("DMSDOS: truncate ino=%ld\n",inode->i_ino);*/
  583.         if(dostest(inode))
  584. #ifdef __FOR_KERNEL_1_3_8x
  585.                    fat_truncate(inode);
  586. #else 
  587.                    msdos_truncate(inode);
  588. #endif
  589.         else dmsdos_truncatex(inode);
  590.         /*printk("DMSDOS truncate finished\n");*/
  591. }
  592.  
  593. void dmsdos_put_inode(struct inode *inode)
  594. {    /*printk("DMSDOS: put inode ino=%ld\n",inode->i_ino);*/
  595.         if(dostest(inode))
  596. #ifdef __FOR_KERNEL_1_3_8x 
  597.                     fat_put_inode(inode);
  598. #else
  599.                     msdos_put_inode(inode);
  600. #endif
  601.         else dmsdos_put_inodex(inode);
  602.         /*printk("DMSDOS put inode finished\n");*/
  603. }
  604.  
  605. void dmsdos_put_super(struct super_block *sb)
  606. {     /*printk("DMSDOS put super\n");*/
  607.         exit_dbl(sb);
  608. #ifdef SUPPORT_VFAT
  609.         if(isvfat(sb))vfat_put_super(sb); else
  610. #endif
  611.         msdos_put_super(sb);
  612.         /*printk("DMSDOS put super finished\n");*/
  613.         MOD_DEC_USE_COUNT;
  614. }
  615.  
  616. static struct super_operations dmsdos_sops = { 
  617.     dmsdos_read_inode,
  618.     dmsdos_notify_change,
  619.     dmsdos_write_inode,
  620.     dmsdos_put_inode,
  621.     dmsdos_put_super,
  622.     NULL, /* added in 0.96c */
  623.     dmsdos_statfs,
  624.     NULL
  625. };
  626.  
  627. /* evaluates a single option
  628.    if not dmsdos, append to msdos option string
  629. */
  630. void evaluate_option(char*option,char*msdosoptions,int*comp,int*cf,int*ilong,
  631.                      int*vfat,int*low,int*nofix)
  632. {  /*printk("DMSDOS: evaluate option: %s\n",option);*/ 
  633.    if(strncmp(option,"comp=",5)==0)
  634.    {  if(strncmp(option+5,"no",2)==0)*comp=UNCOMPRESSED;
  635.       if(strncmp(option+5,"ro",2)==0)*comp=READ_ONLY;
  636.       if(strncmp(option+5,"ds00",4)==0)*comp=DS_0_0;
  637.       if(strncmp(option+5,"ds01",4)==0)*comp=DS_0_1;
  638.       if(strncmp(option+5,"ds02",4)==0)*comp=DS_0_2;
  639.       if(strncmp(option+5,"jm00",4)==0)*comp=JM_0_0;
  640.       if(strncmp(option+5,"jm01",4)==0)*comp=JM_0_1;
  641.       if(strncmp(option+5,"sq00",4)==0)*comp=SQ_0_0;
  642.       if(strncmp(option+5,"guess",5)==0)*comp=GUESS;
  643.    }
  644.    else if(strncmp(option,"cf=",3)==0)
  645.    {  if(option[3]=='1'&&option[4]>='0'&&option[4]<='2')*cf=option[4]-'0'+9;
  646.       else if(option[3]>='1'&&option[3]<='9')*cf=option[3]-'0'-1;
  647.    }
  648.    else if(strncmp(option,"long=",5)==0)
  649.    {  if(strncmp(option+5,"on",2)==0)*ilong=1;
  650.       if(strncmp(option+5,"off",3)==0)*ilong=0;
  651.       if(strncmp(option+5,"auto",4)==0)*ilong=2;
  652.       if(strncmp(option+5,"always",6)==0)*ilong=17;
  653.    }
  654.    else if(strncmp(option,"vfat",4)==0)*vfat=1;
  655.    else if(strncmp(option,"low",3)==0)*low=1;
  656.    else if(strncmp(option,"nofix",5)==0)*nofix=1;
  657.    else
  658.    {  if(strlen(msdosoptions)!=0)strcat(msdosoptions,",");
  659.       strcat(msdosoptions,option);
  660.    }
  661. }
  662.  
  663. struct super_block *dmsdos_read_super(struct super_block *sb,void *data,
  664.                      int silent)
  665. {    struct super_block *s;
  666.         int comp,cf,i,ilong,vfat,low,nofix;
  667.         char *options=data;
  668.         char myoptions[512];
  669.         char msdosoptions[512];
  670.         char * akt_option;
  671.  
  672.         /*printk("DMSDOS read_super\n");*/
  673.         comp=DEFAULT_COMP;
  674.         cf=DEFAULT_CF;
  675.         ilong=2; /* auto lfn */
  676.         vfat=0;  /* off */
  677.         low=0;   /* no low option specified */
  678.         nofix=0; /* perform fixdir when drivespace 3 rw */
  679.         
  680.         MOD_INC_USE_COUNT;
  681.         /* scan option string */
  682.         /*printk("DMSDOS: option string: %s\n",options);*/
  683.         
  684.         if(options==NULL)msdosoptions[0]='\0';
  685.         else
  686.         { /* copy option string */
  687.           strcpy(myoptions,options);
  688.           
  689.           /* separate options */
  690.           akt_option=myoptions;
  691.           msdosoptions[0]='\0';
  692.           for(i=0;i<=strlen(options);++i)
  693.           { if(myoptions[i]==','||myoptions[i]=='\0')
  694.             { myoptions[i]='\0';
  695.               evaluate_option(akt_option,msdosoptions,&comp,&cf,&ilong,&vfat,
  696.                               &low,&nofix);
  697.               akt_option=&(myoptions[i+1]);
  698.             }
  699.           } 
  700.         }
  701.         
  702.         /*printk("DMSDOS: msdosoptions: %s\n",msdosoptions);*/
  703.         
  704.         s=
  705. #ifdef SUPPORT_VFAT
  706.               vfat ? vfat_read_super(sb,msdosoptions,silent) :
  707. #endif
  708.               msdos_read_super(sb,msdosoptions,silent);
  709.         if(s==NULL)
  710.         { MOD_DEC_USE_COUNT;
  711.           return NULL;
  712.         }
  713.         s->s_op=&dmsdos_sops;
  714.         /* dmsdos fs must be read-only if msdos fs is read-only */
  715.         if(s->s_flags&MS_RDONLY)comp=READ_ONLY;
  716.         if(dbl_init(s,data,comp,cf,ilong,vfat,low,nofix)<0)
  717.         { s->s_dev=0;
  718.           MOD_DEC_USE_COUNT;
  719.           return NULL;
  720.         }
  721.         /*printk("DMSDOS read_super finished\n");*/
  722.         return s;
  723. }
  724.  
  725. #ifdef __FOR_KERNEL_1_3
  726. void dmsdos_statfs(struct super_block *sb,struct statfs *buf,int i)
  727. {    /*printk("DMSDOS statfs\n");*/
  728. #ifdef __FOR_KERNEL_1_3_8x
  729.         fat_statfs(sb,buf,i);
  730. #else
  731.         msdos_statfs(sb,buf,i);
  732. #endif
  733.         /*printk("DMSDOS statfs finished\n");*/
  734. }
  735. #else
  736. void dmsdos_statfs(struct super_block *sb,struct statfs *buf)
  737. {    /*printk("DMSDOS statfs\n");*/
  738.         msdos_statfs(sb,buf);
  739.         /*printk("DMSDOS statfs finished\n");*/
  740. }
  741. #endif
  742.  
  743. void dmsdos_read_inode(struct inode *inode)
  744. {    /*printk("DMSDOS read_inode ino=%ld\n",inode->i_ino);*/
  745.         if(dostest(inode))
  746.         {
  747. #ifdef SUPPORT_VFAT
  748.               if(isvfat(inode->i_sb))vfat_read_inode(inode); else
  749. #endif       
  750.                    msdos_read_inode(inode);
  751.         }
  752.     else dmsdos_read_inodex(inode);
  753.     /*printk("DMSDOS read inode finished\n");*/
  754. }
  755.  
  756. void dmsdos_write_inode(struct inode *inode)
  757. {    /*printk("DMSDOS write inode ino=%ld\n",inode->i_ino);*/
  758.         if(dostest(inode))
  759. #ifdef __FOR_KERNEL_1_3_8x
  760.                     fat_write_inode(inode);
  761. #else 
  762.                     msdos_write_inode(inode);
  763. #endif
  764.         dmsdos_write_inodex(inode);
  765.         /*printk("DMSDOS write inode finished\n");*/
  766. }
  767.  
  768. int dmsdos_notify_change(struct inode * inode,struct iattr * attr)
  769. {    int res;
  770.  
  771.         /*printk("DMSDOS notify_change ino=%ld\n",inode->i_ino);*/
  772.         if(dostest(inode))res=
  773. #ifdef __FOR_KERNEL_1_3_8x
  774.                  fat_notify_change(inode,attr);
  775. #else 
  776.                  msdos_notify_change(inode,attr);
  777. #endif
  778.         else res=dmsdos_notify_changex(inode,attr);
  779.         /*printk("DMSDOS notify change finished res=%d\n",res);*/
  780.         return res;
  781. }
  782.  
  783. /*
  784.  * Fill in the supplied page for mmap
  785.  */
  786. static unsigned long dmsdos_file_mmap_nopage(
  787.     struct vm_area_struct * area,
  788.     unsigned long address,
  789. #ifndef __FOR_KERNEL_1_3_8x
  790.     unsigned long page,
  791. #endif
  792.     int error_code)
  793. {
  794.     struct inode * inode = area->vm_inode;
  795.     unsigned int clear;
  796.     int pos;
  797.     long gap;    /* distance from eof to pos */
  798.     
  799.     /*printk("DMSDOS_file_mmap_nopage\n");*/
  800.  
  801. #ifdef __FOR_KERNEL_1_3_8x
  802.         unsigned long int page = __get_free_page(GFP_KERNEL);
  803.         if(!page)return page;                        
  804. #endif
  805.     address &= PAGE_MASK;
  806.     pos = address - area->vm_start + area->vm_offset;
  807.  
  808.     clear = 0;
  809.     gap = inode->i_size - pos;
  810.     if (gap <= 0){
  811.         /* mmaping beyond end of file */
  812.         clear = PAGE_SIZE;
  813.     }else{
  814.         int cur_read;
  815.         int need_read;
  816.         struct file filp;
  817.         if (gap < PAGE_SIZE){
  818.             clear = PAGE_SIZE - gap;
  819.         }
  820.         filp.f_reada = 0;
  821.         filp.f_pos = pos;
  822.         need_read = PAGE_SIZE - clear;
  823.         {
  824.             unsigned long cur_fs = get_fs();
  825.             set_fs (KERNEL_DS);
  826.             cur_read = dmsdos_file_read (inode,&filp,(char*)page
  827.                 ,need_read);
  828.             set_fs (cur_fs);
  829.         }
  830.         if (cur_read != need_read){
  831.             printk ("DMSDOS: Error while reading an mmap file %d <> %d\n"
  832.                 ,cur_read,need_read);
  833.         }
  834.     }
  835.     if (clear > 0){
  836.         memset ((char*)page+PAGE_SIZE-clear,0,clear);
  837.     }
  838.     return page;
  839. }
  840.  
  841. struct vm_operations_struct dmsdos_file_mmap = {
  842.     NULL,            /* open */
  843.     NULL,            /* close */
  844.     NULL,            /* unmap */
  845.     NULL,            /* protect */
  846.     NULL,            /* sync */
  847.     NULL,            /* advise */
  848.     dmsdos_file_mmap_nopage,    /* nopage */
  849.     NULL,            /* wppage */
  850.     NULL,            /* swapout */
  851.     NULL,            /* swapin */
  852. };
  853.  
  854. /*
  855.  * This is used for a general mmap of a dmsdos file
  856.  * Returns 0 if ok, or a negative error code if not.
  857.  */
  858. int dmsdos_mmapx(struct inode*inode,struct file*file,struct vm_area_struct*vma)
  859. {
  860.     /*printk("DMSDOS mmap ino=%ld\n",inode->i_ino);*/
  861.     if (vma->vm_flags & VM_SHARED)    /* only PAGE_COW or read-only supported now */
  862.         return -EINVAL;
  863.     if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
  864.         return -EINVAL;
  865.     if (!inode->i_sb || !S_ISREG(inode->i_mode))
  866.         return -EACCES;
  867.     if (!IS_RDONLY(inode)) {
  868.         inode->i_atime = CURRENT_TIME;
  869.         inode->i_dirt = 1;
  870.     }
  871.  
  872.     vma->vm_inode = inode;
  873.     inode->i_count++;
  874.     vma->vm_ops = &dmsdos_file_mmap;
  875.     return 0;
  876. }
  877.  
  878. int dmsdos_mmap(struct inode*inode,struct file*file,struct vm_area_struct*vma)
  879. {       int res;
  880.  
  881.     /*printk("DMSDOS mmap ino=%ld\n",inode->i_ino);*/
  882.         if(dostest(inode)) res=
  883. #ifdef __FOR_KERNEL_1_3_8x
  884.                       fat_mmap(inode,file,vma);
  885. #else
  886.                       msdos_mmap(inode,file,vma);
  887. #endif
  888.         else res=dmsdos_mmapx(inode,file,vma);
  889.         /*printk("DMSDOS mmap finished res=%d\n",res);*/
  890.         return res;
  891. }
  892.  
  893. int dmsdos_lookup(struct inode *dir,const char *name,int len,
  894.     struct inode **result)
  895. {    int res;
  896.  
  897.         /*printk("DMSDOS lookup ino=%ld name=%s\n",dir->i_ino,name);*/
  898.         if(dostest(dir)) res=
  899. #ifdef SUPPORT_VFAT
  900.                      isvfat(dir->i_sb) ? vfat_lookup(dir,name,len,result) :
  901. #endif
  902.                      msdos_lookup(dir,name,len,result);
  903.     else res=dmsdos_lookupx(dir,name,len,result);
  904.     /*printk("DMSDOS lookup finished res=%d\n",res);*/
  905.     return res;
  906. }
  907.